﻿using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace IIOS.SP.WebParts.Navigation.WebAppNavigator
{
    [ToolboxItemAttribute(false)]
    public class WebAppNavigator : WebPart //Microsoft.SharePoint.WebPartPages.WebPart
    {
        #region properties

        private bool bError;
        private bool bSelect;
        private bool bUseFullWidth = true;
        private bool bUseTree;
        private SPList oList;
        private AspMenu oMenu;
        private GTreeView oMenuTree;
        private SPWeb oWeb;
        private string sNavId;
        private string sNavigationList = "Navigation";
        private string sQuery = "<Where><And><Eq><FieldRef Name='Display' /><Value Type='Boolean'>1</Value></Eq><Eq><FieldRef Name='ParentLink' LookupId='TRUE' /><Value Type='Lookup' LookupId='true'>{0}</Value></Eq></And></Where><OrderBy><FieldRef Name='Position' Ascending='True' /></OrderBy>";


        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable(true),
        Category("Navigator Configuration"),
        WebDisplayName("List Name"),
        WebDescription("The name of the list containing Navigation links and properties. The list must have all required fields")]
        public string NavigationList
        {
            get { return sNavigationList; }
            set { sNavigationList = value; }
        }

        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable(true),
        Category("Navigator Configuration"),
        WebDisplayName("Display Tree"),
        WebDescription("If this is selected, it will render the Navigation menu as a Tree")]
        public bool UseTree
        {
            get { return bUseTree; }
            set { bUseTree = value; }
        }

        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable(true),
        Category("Navigator Configuration"),
        WebDisplayName("Use Full Width"),
        WebDescription("If this is selected, it will render the Navigation menu using 100% of available width")]
        public bool UseFullWidth
        {
            get { return bUseFullWidth; }
            set { bUseFullWidth = value; }
        }
        #endregion

        #region MenuMethods

        public WebAppNavigator()
        {
            this.ExportMode = WebPartExportMode.All;
        }

        protected void buildHierarchy(MenuItem oMenuItem)
        {
            try
            {
                SPQuery query = new SPQuery {
                    Query = string.Format(this.sQuery, oMenuItem.Value)
                };
                foreach (SPListItem item in this.oList.GetItems(query))
                {
                    MenuItem item2 = new MenuItem(item["Title"].ToString(), item["ID"].ToString(), "", item["Location"].ToString(), "_top");
                    if (!this.bSelect && (this.oWeb.ServerRelativeUrl == item2.NavigateUrl))
                    {
                        this.bSelect = true;
                    }
                    SPQuery query2 = new SPQuery {
                        Query = string.Format(this.sQuery, item2.Value)
                    };
                    if (this.oList.GetItems(query2).Count > 0)
                    {
                        try
                        {
                            this.buildHierarchy(item2);
                        }
                        catch
                        {
                        }
                    }
                    oMenuItem.ChildItems.Add(item2);
                }
            }
            catch
            {
            }
        }

        protected void buildHierarchy(TreeNode oTreeNode)
        {
            try
            {
                SPQuery query = new SPQuery {
                    Query = string.Format(this.sQuery, oTreeNode.Value)
                };
                foreach (SPListItem item in this.oList.GetItems(query))
                {
                    TreeNode node = new TreeNode(item["Title"].ToString(), item["ID"].ToString(), "", item["Location"].ToString(), "_top");
                    node.Collapse();
                    if (this.sNavId == node.Value)
                    {
                        node.Selected = true;
                        node.Expand();
                        oTreeNode.Expand();
                        this.bSelect = true;
                    }
                    SPQuery query2 = new SPQuery {
                        Query = string.Format(this.sQuery, node.Value)
                    };
                    if (this.oList.GetItems(query2).Count > 0)
                    {
                        try
                        {
                            this.buildHierarchy(node);
                        }
                        catch
                        {
                        }
                    }
                    oTreeNode.ChildNodes.Add(node);
                }
            }
            catch
            {
            }
        }

        protected void buildNavigationMenu()
        {
            this.oWeb = SPControl.GetContextWeb(this.Context);
            SPSecurity.RunWithElevatedPrivileges(delegate {
                try
                {
                    this.oList = this.oWeb.Lists[this.sNavigationList];
                }
                catch
                {
                    try
                    {
                        SPSite site = new SPSite(this.oWeb.Site.WebApplication.Sites[0].ID, this.oWeb.Site.SystemAccount.UserToken);
                        SPWeb rootWeb = site.RootWeb;
                        this.oList = rootWeb.Lists[this.sNavigationList];
                        rootWeb.Dispose();
                        site.Dispose();
                    }
                    catch
                    {
                        this.HandleException(string.Format("List {0} is missing from the local site and the root site", this.sNavigationList));
                    }
                }
            });
            try
            {
                SPQuery query = new SPQuery {
                    Query = "<Where><And><Eq><FieldRef Name='Display' /><Value Type='Boolean'>1</Value></Eq><IsNull><FieldRef Name='ParentLink' /></IsNull></And></Where><OrderBy><FieldRef Name='Position' Ascending='True' /></OrderBy>"
                };
                foreach (SPListItem item in this.oList.GetItems(query))
                {
                    if (!this.hasAccess(item["Location"].ToString()) && (bool)item["SecTrim"]==true)
                    {
                        continue;
                    }
                    this.bSelect = false;
                    if (this.bUseTree)
                    {
                        TreeNode oTreeNode = new TreeNode(item["Title"].ToString(), item["ID"].ToString(), "", item["Location"].ToString(), "_top");
                        oTreeNode.Collapse();
                        if (this.sNavId == oTreeNode.Value)
                        {
                            oTreeNode.Selected = true;
                            oTreeNode.Expand();
                        }
                        this.buildHierarchy(oTreeNode);
                        if (this.bSelect)
                        {
                            oTreeNode.Expand();
                        }
                        this.oMenuTree.Nodes.Add(oTreeNode);
                        continue;
                    }
                    MenuItem oMenuItem = new MenuItem(item["Title"].ToString(), item["ID"].ToString(), "", item["Location"].ToString(), "_top");
                    if (!this.bSelect && ((this.oWeb.ServerRelativeUrl == oMenuItem.NavigateUrl) || (this.Page.Request.Path == oMenuItem.NavigateUrl)))
                    {
                        oMenuItem.Selected = true;
                        this.bSelect = true;
                    }
                    this.buildHierarchy(oMenuItem);
                    if (this.bSelect)
                    {
                        oMenuItem.Selected = true;
                    }
                    this.oMenu.Items.Add(oMenuItem);
                }
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
            }
        }

        protected override void CreateChildControls()
        {
            if (!this.bError)
            {
                try
                {
                    base.CreateChildControls();
                    this.setupMenu();
                    if (!this.bError)
                    {
                        if (this.bUseTree)
                        {
                            this.Controls.Add(this.oMenuTree);
                        }
                        else
                        {
                            this.Controls.Add(this.oMenu);
                        }
                    }
                }
                catch (Exception exception)
                {
                    this.HandleException(exception);
                }
            }
        }

        private void HandleException(Exception ex)
        {
            this.bError = true;
            this.Controls.Clear();
            this.Controls.Add(new LiteralControl(ex.Message));
        }

        private void HandleException(string s)
        {
            this.bError = true;
            this.Controls.Clear();
            this.Controls.Add(new LiteralControl(s));
        }

        protected bool hasAccess(string sURL)
        {
            bool flag;
            if (sURL.IndexOf("http://") < 0)
            {
                sURL = string.Format("http://{0}:{1}{2}", this.Page.Request.Url.Host, this.Page.Request.Url.Port, this.Page.ResolveUrl(sURL));
            }
            try
            {
                using (SPSite site = new SPSite(sURL, this.oWeb.Site.SystemAccount.UserToken))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        flag = web.DoesUserHavePermissions(this.oWeb.CurrentUser.LoginName, SPBasePermissions.EmptyMask | SPBasePermissions.ViewPages);
                    }
                }
            }
            catch
            {
                flag = true;
            }
            return flag;
        }

        private void oMenu_MenuItemClick(object sender, MenuEventArgs e)
        {
            this.sNavId = e.Item.Value;
        }

        private void oMenuTree_Select(object sender, EventArgs e)
        {
            this.sNavId = this.oMenuTree.SelectedValue;
        }

        private void oMenuTree_SelectedNodeChanged(object sender, EventArgs e)
        {
            this.sNavId = this.oMenuTree.SelectedValue;
        }

        protected override void OnLoad(EventArgs e)
        {
            if (!this.bError)
            {
                try
                {
                    base.OnLoad(e);
                    this.EnsureChildControls();
                }
                catch (Exception exception)
                {
                    this.HandleException(exception);
                }
            }
        }

        protected void setupMenu()
        {
            if (!this.bUseTree)
            {
                this.oMenu = new AspMenu();
                this.oMenu.ID = "IIOSNavigation";
                this.oMenu.EnableViewState = false;
                this.oMenu.Orientation = Orientation.Horizontal;
                this.oMenu.StaticDisplayLevels = 1;
                this.oMenu.MaximumDynamicDisplayLevels = 5;
                this.oMenu.UseSimpleRendering = true;
                this.oMenu.UseSeparateCSS = false;
                this.oMenu.CssClass = "s4-tn";
                this.oMenu.SkipLinkText = "";
                if (this.UseFullWidth)
                {
                    this.oMenu.Width = Unit.Percentage(100.0);
                }
                else
                {
                    this.oMenu.Width = Unit.Empty;
                }
                this.oMenu.MenuItemClick += new MenuEventHandler(this.oMenu_MenuItemClick);
            }
            else
            {
                this.oMenuTree = new GTreeView();
                this.oMenuTree.ShowExpandCollapse = true;
                this.oMenuTree.ShowLines = true;
                this.oMenuTree.NodeWrap = false;
                this.oMenuTree.SelectedNodeStyle.CssClass = "ms-tvselected";
                this.oMenuTree.NodeStyle.CssClass = "ms-navitem";
                this.oMenuTree.ExpandImageUrl = "/_layouts/images/tvplus.gif";
                this.oMenuTree.CollapseImageUrl = "/_layouts/images/tvminus.gif";
                this.oMenuTree.NoExpandImageUrl = "/_layouts/images/tvblank.gif";
                this.oMenuTree.SelectedNodeChanged += new EventHandler(this.oMenuTree_SelectedNodeChanged);
                this.oMenuTree.Select += new EventHandler(this.oMenuTree_Select);
            }
            this.buildNavigationMenu();
        }
            #endregion
    }
}
